package cn.devzyh.oms.coms.order.service;

import cn.devzyh.oms.common.core.constant.SecurityConstants;
import cn.devzyh.oms.common.core.message.ComsErrorCodes;
import cn.devzyh.oms.common.core.util.R;
import cn.devzyh.oms.coms.api.express.dto.LocationDTO;
import cn.devzyh.oms.coms.api.order.dto.OrderDTO;
import cn.devzyh.oms.coms.api.order.entity.OrderDetail;
import cn.devzyh.oms.coms.api.order.entity.OrderHeader;
import cn.devzyh.oms.coms.express.service.AreaService;
import cn.devzyh.oms.coms.flow.context.FlowContext;
import cn.devzyh.oms.coms.flow.executor.FlowNode;
import cn.devzyh.oms.wsms.api.dto.MatchWarehouseDTO;
import cn.devzyh.oms.wsms.api.feign.RemoteWarehouseService;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.Set;

/**
 * 匹配仓库工作流节点
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MatchWarehouseNode implements FlowNode {

	private final RemoteWarehouseService remoteWarehouseService;

	private final AreaService areaService;

	private final OrderHeaderService orderHeaderService;

	private static final String WAREHOUSE_CODE = "warehouseCode";

	@Override
	public R process(FlowContext ctx) {
		OrderDTO order = (OrderDTO) ctx.getMainCache();
		OrderHeader header = order.getHeader();

		LocationDTO location = areaService.getReceiveLocation(header);
		if (location == null) {
			return R.failedMessage(ComsErrorCodes.AREA_NOT_EXISTS, header.getId().toString());
		}

		MatchWarehouseDTO dto = new MatchWarehouseDTO();
		dto.setWarehouseCode(header.getWarehouseCode());
		dto.setLatitude(location.getLatitude());
		dto.setLongitude(location.getLongitude());
		Set<String> skuCodes = new HashSet<>();
		for (OrderDetail detail : order.getDetails()) {
			skuCodes.add(detail.getSkuCode());
		}
		dto.setSkuCodes(skuCodes);

		R res = remoteWarehouseService.match(dto, SecurityConstants.FROM_IN);
		if (res.success()) {
			header.setWarehouseCode(res.getData().toString());
			LambdaUpdateWrapper<OrderHeader> wrapper = Wrappers.lambdaUpdate();
			wrapper.set(OrderHeader::getWarehouseCode, header.getWarehouseCode());
			wrapper.eq(OrderHeader::getId, header.getId());
			orderHeaderService.update(wrapper);
		}

		ctx.addResult(WAREHOUSE_CODE, header.getWarehouseCode());

		return res;
	}

}
